1 Introduction

In statistical inference, point estimation refers to the process of using sample data to calculate a single value (called a point estimate) that serves as a “best guess” or “best estimate” of an unknown population parameter. Some technical terms

  • Point estimator: A function of the sample data used to estimate an unknown parameter \(\theta\) of a population.

  • Statistic: A function of the sample data only (no unknown parameters).

  • Sample space: The set of all possible samples (data sets) that could be observed.

  • Parameter space: The set of all possible values of the parameter \(\theta\).

In the subsequent sections, we will introduce some notations and formalize the above concepts as well as some theories about estimations and a special point estimtor - method of moment (MoM).

2 Basics of Point Estimation

This section will cover the core concepts of point estimation, including the criteria for a good estimator—such as unbiasedness, consistency, and efficiency—and introduce common methods for deriving these estimates, like maximum likelihood estimation. Understanding these basics provides the critical foundation for all subsequent statistical inference, from constructing confidence intervals to testing hypotheses.

2.1 Notations and Definitions

To summarize the basic properties of point estimate of population parameters. We introduce some notations. Let:

  • \(X_1, X_2, \ldots, X_n\) be a random sample from a population distribution \(f(x|\theta)\), where \(\theta\) is an unknown parameter. It is often denoted by \(F_\theta(x)\).

  • \(\Theta\) be the parameter space - possible values of \(\theta\).

  • \(\mathcal{X}\) be the sample space - possible values of \(x\).

A statistic is a function \(T: \mathcal{X} \to \mathbb{R}^k\) for some \(k\) that does not dependent on \(\theta\)

A point estimator \(\hat{\theta}\) of \(\theta\) is a statistic whose range (parameter space) is \(\Theta\) (or at least a subset of it),

\[ \hat{\theta} = T(X_1, X_2, \cdots, X_n). \]

\[ \hat{\theta}: \mathcal{X} \to \Theta, \] that is, For a given point \(\mathbf{X} = (X_1, X_2, \cdots, X_n)\) in a sample space \(\mathcal{X}\): \(\mathbb{X} \in \mathcal{X}\),

\[ \hat{\theta}(\mathbf{X}) \in \Theta \]

and \(\hat{\theta}\) is a statistic.

Example: Suppose \(X_1, X_2, \cdots, X_n \to N(\mu, \sigma_0^2)\), \(\sigma_0^2\) is a known population variance. We want to estimate \(\mu \in \mathbb{R} = \Theta\).

  • \((X_1, X_2, \cdots, X_n) \in \mathbb{R}^n\). That is, \(n\)-dimensional vector \((X_1, X_2, \cdots, X_n)\) is a point in the \(n\)-dimensional space \(\mathbb{R}^n\).

  • Parameter space \(\Theta = \mathbb{R}\). That is, \(\mu\) is a point in the one dimensional space \(\mathbb{R}\).

  • A point estimator \(\hat{\mu}(\mathbf{X}) = \bar{X} = (\sum_{i=1}^n X_i)/n\).

Clearly,

  • \(\hat{\mu}\) is a statistic (depends only on sample).

  • \(\hat{\mu}: \mathbb{R}^n\equiv \mathcal{X} \to \mathbb{R} \equiv \Theta\) maps sample space to parameter space.


2.2 Properties of Point Estimate

1. Unbiasedness

An estimator \(\hat{\theta}\) is unbiased if \(E[\hat{\theta}] = \theta\).

The bias of an estimator is defined as: \[ \text{Bias}(\hat{\theta}) = E(\hat{\theta}) - \theta \] 2. Consistency

An estimator is consistent if:

\[ \lim_{n\to \infty} P(|\hat{\theta}-\theta|>\epsilon) = 0, \ \ \text{ for all } \epsilon > 0. \]3. Efficiency

Among unbiased estimators, the one with smaller variance is more efficient. The Cramér-Rao lower bound gives the minimum possible variance for an unbiased estimator:

\[ \text{Var}(\hat{\theta}) \ge \frac{1}{I_n(\theta)}=\frac{1}{nI_0(\theta)} \]

where \(I_0(\theta)\) is the Fisher information that measures the amount of information that a sample \(\{X\}\) carries about the unknown population parameter \(\theta\) to be estimated. To calculate the Fisher Information of a univariate parameter, we only need to find the negative expected value of the 2nd order derivative of the log density function (continuous RV) or mass function (for discrete RV) as follows

\[ I_0(\theta) = -E_X\left[ \frac{d^2}{d\theta^2} \log f(X: \theta)\right] \]

Example: Consider Poisson distribution

\[ P(X=k) = \frac{\lambda^k e^{-\lambda}}{k!}, \ \ \lambda = 0, 1, 2, \cdots \]

Based on the above definition of the Fisher Information of \(\lambda\), we calculate \(I_0(\lambda)\) in the following steps

  1. Let \(L(\lambda) = f(X:\lambda) = \lambda^X e^{-\lambda}/X!\)

  2. \(\ell(\lambda) = \log L(\lambda) = -\lambda + X\log(\lambda) - \log(X!)\)

  3. Taking the first order derivative \(\ell(\lambda)\), we get \(\ell^\prime(\lambda) = -1 + X/\lambda\).

  4. Taking the second order derivetive \(\ell(\lambda)\), we get \(\ell^{\prime\prime}(\lambda) = -x/\lambda^2\)

  5. \(I_0(\lambda) = -E_X[\ell^{\prime\prime}(\lambda)] = -E_X[-X/\lambda^2] = E_X[X]/\lambda^2 = 1/\lambda\).

4. Mean Squared Error (MSE)

The MSE combines both variance and bias:

\[ MSE(\hat{\theta}) = E[(\hat{\theta} - \theta)^2] = \text{Var}(\hat{\theta}) + [\text{Bias}(\hat{\theta})]^2 \]

3 Method of Moments Estimation

The Method of Moments (MoM) is one of the oldest and most intuitive approaches to parameter estimation. The basic idea is to equate population moments with sample moments and solve for the parameters.

3.1 Population and Sample Moments

Recall that the \(k\)-th population moment about the origin is

\[ \mu^k=E[X^k]. \]

Clearly, the \(k\)-th moment is a function of population parameters only. It is independent on the observed data.

On the the \(k\)-th sample moment is:

\[ m_k = \frac{1}{n}\sum_{i=1}^n X_i^k \]

The theoretical moments can be derived from the moment generating function of a specified model (parameteric distribution).

3.2 Procedure for Method of Moment Estimation

The fundamental logic of the moment estimation is to make the properties of the sample match the properties of the theoretical probability model. Since the theoretical model’s properties (like mean, variance) depend on its unknown parameters, we can set up equations to solve for those parameters. This logic is a straightforward application of the analogy principle: if the model is correct, then the sample should reflect it.

Estimation Procedure

For a distribution with \(p\) parameters \(\theta_1, \theta_2, \ldots, \theta_p\):

  1. Express population moments in terms of parameters - \(k\)-th theoretical moment:

\[ \mu_k = h_k(\theta_1, \theta_2, \cdots, \theta_p) \]

for \(k = 1, 2, \cdots, p\) are po

  1. Equate population moments with sample moments:

\[ h_k(\theta_1, \theta_2, \cdots, \theta_p) = m_k \] for \(k=1,2,\cdots,p\)

  1. Solve the system of equations to obtain MoM estimators \(\hat{\theta}_1, \hat{\theta}_2, \ldots, \hat{\theta}_p\)

To explain the computing efforts, we re-express the above system of \(p\) equations explicitly in the following

\[ \begin{align*} \mu_1(\theta_1, \dots, \theta_p) &= m_1 \\ \mu_2(\theta_1, \dots, \theta_p) &= m_2 \\ &\vdots \\ \mu_p(\theta_1, \dots, \theta_p) &= m_p \end{align*} \]

In general, the above equations are nonlinear. This means that numerical methods are required to solve the system of equations. In the next section, we will use several examples to show how to moment of estimation based on some special models learned in the previous class.

4 Examples of Method of Moments Estimation

This section focuses on three examples using well-known models.

4.1 Example 1: Normal Distribution

Consider \(\{X_1, X_2, \cdots, X_n \} \sim N(\mu, \sigma^2)\), we will use method of moment to estimate the two parameters \(\theta = (\mu, \sigma^2)\).

Since there are two parameters in the model, we need to calculate the first and second population moments and the corresponding sample moments as follows.

  • Population moments are calculated in the following:

\[ \begin{aligned} \mu_1 &= E[X] = \mu \\ \mu_2 &= E[X^2] = \sigma^2 + \mu^2 \end{aligned} \]

  • Sample moments:

\[ \begin{aligned} m_1 &= \frac{1}{n} \sum_{i=1}^n X_i \\ m_2 &= \frac{1}{n} \sum_{i=1}^n X_i^2 \end{aligned} \]

The method of moment estimator is the solution to the following system of equations

\[ \begin{aligned} \mu &= \frac{1}{n} \sum_{i=1}^n X_i \\ \sigma^2 + \mu^2 &= \frac{1}{n} \sum_{i=1}^n X_i^2 \end{aligned} \]

Solveing the above system of nonlinear equations, we have

\[ \begin{align*} \hat{\mu} &= \frac{1}{n} \sum_{i=1}^n X_i & = \bar{X} \\ \hat{\sigma}^2 &= \frac{1}{n} \sum_{i=1}^n X_i^2 - \bar{X}^2 &= \frac{1}{n}\sum_{i=1}^n(X_i-\bar{X})^2 \end{align*} \]

Next, we implement the above MME through a simulated data in R.

# Example: MoM for Normal Distribution
set.seed(123)
n <- 1000
true_mu <- 5
true_sigma <- 2

# Generate sample data
sample_data <- rnorm(n, mean = true_mu, sd = true_sigma)

# Method of Moments estimation
mom_mu <- mean(sample_data)
mom_sigma_sq <- mean(sample_data^2) - mom_mu^2
mom_sigma <- sqrt(mom_sigma_sq)

cat("True parameters: μ =", true_mu, ", σ =", true_sigma, "\n")
True parameters: μ = 5 , σ = 2 
cat("MoM estimates: μ_hat =", round(mom_mu, 3), 
    ", σ_hat =", round(mom_sigma, 3), "\n")
MoM estimates: μ_hat = 5.032 , σ_hat = 1.982 

4.2 Example 2: Gamma Distribution

For \(X \sim \text{Gamma}(\alpha, \beta)\), with PDF:

\[ f(x \mid \alpha, \beta) = \frac{\beta^{\alpha}}{\Gamma(\alpha)} x^{\alpha - 1} e^{-\beta x} \quad \text{for } x > 0 \]

We know that the top population moments are given in the following

\[ \begin{align*} \mu_1 &= E[X] = \frac{\alpha}{\beta} \\[2mm] \mu_2 &= E[X^2] = \frac{\alpha(\alpha + 1)}{\beta^2} \end{align*} \]

Assume the first and second moments to be \(m_1\) and \(m_2\). We set up the following system of equations

\[ \begin{align*} m_1 & = \frac{\alpha}{\beta} \\[2mm] m_2 & = \frac{\alpha(\alpha + 1)}{\beta^2} \end{align*} \]

Solving for parameters \(\alpha\) and \(\beta\) from the above system of equation to get the the estimators based on the method of moment estimation:

\[ \begin{align*} \hat{\beta} &= \frac{m_1}{m_2 - m_1^2} \\[2mm] \hat{\alpha} &= m_1 \hat{\beta} = \frac{m_1^2}{m_2 - m_1^2} \end{align*} \]

The following is the implementation of the above MME through a simulated data in R.

# Example: MoM for Gamma Distribution
set.seed(123)
n <- 1000
true_alpha <- 3
true_beta <- 2

# Generate sample data
sample_gamma <- rgamma(n, shape = true_alpha, rate = true_beta)

# Method of Moments estimation
m1 <- mean(sample_gamma)
m2 <- mean(sample_gamma^2)

mom_beta <- m1 / (m2 - m1^2)
mom_alpha <- m1 * mom_beta

cat("True parameters: α =", true_alpha, ", β =", true_beta, "\n")
True parameters: α = 3 , β = 2 
cat("MoM estimates: α_hat =", round(mom_alpha, 3), 
    ", β_hat =", round(mom_beta, 3), "\n")
MoM estimates: α_hat = 3.309 , β_hat = 2.297 

Example 3. Weibull Distribution

The Weibull distribution has probability density function:

\[ f(x \mid \lambda, k) = \frac{k}{\lambda} \left( \frac{x}{\lambda} \right)^{k-1} e^{-(x/\lambda)^k} \quad \text{for } x \geq 0 \]

where

  • \(k>0\) is the shape parameter

  • \(\lambda > 0\) is the scale parameter

The first and second moments of population are

\[ \begin{align*} \mu_1 &= E[X] = \lambda \Gamma\left(1 + \frac{1}{k}\right) \\ \mu_2 &= E[X^2] = \lambda^2 \Gamma\left(1 + \frac{2}{k}\right) \end{align*} \]

The corresponding sample moments are

\[ \begin{align*} m_1 &= \frac{1}{n} \sum_{i=1}^n X_i \\ m_2 &= \frac{1}{n} \sum_{i=1}^n X_i^2 \end{align*} \]

We set population moments equal to sample moments to the following Method of Moments Equations:

\[ \begin{align*} \lambda \Gamma\left(1 + \frac{1}{k}\right) &= m_1 \quad \cdots\cdots\quad\text{(1)}\\ \lambda^2 \Gamma\left(1 + \frac{2}{k}\right) &= m_2 \quad \cdots\cdots\quad\text{(2)} \end{align*} \]

The above system of equations does not have a closed form solution. We next sketch the steps for solving the above nonlinear system.

From equations (1) and (2), we can eliminate \(\lambda\):

Step 1: Square equation (1):

\[ \lambda^2 \left[\Gamma\left(1 + \frac{1}{k}\right)\right]^2 = m_1^2 \]

Step 2: Divide equation (2) by this result:

\[ \frac{\Gamma\left(1 + \frac{2}{k}\right)}{\left[\Gamma\left(1 + \frac{1}{k}\right)\right]^2} = \frac{m_2}{m_1^2} \]

Step 3: Let \(\hat{k}\) be the solution to:

\[ \frac{\Gamma\left(1 + \frac{2}{k}\right)}{\left[\Gamma\left(1 + \frac{1}{k}\right)\right]^2} = \frac{m_2}{m_1^2} \]

Step 4: Once \(\lambda\) is found, obtain \(\hat{\lambda}\) from:

\[ \hat{\lambda} = \frac{m_1}{\Gamma\left(1 + \frac{1}{\hat{k}}\right)} \]

The parameter \(k\) can be solved numerically from the following equation:

\[ g(k) = \frac{\Gamma\left(1 + \frac{2}{k}\right)}{\left[\Gamma\left(1 + \frac{1}{k}\right)\right]^2} - \frac{m_2}{m_1^2} = 0 \]

The method of moments estimation for the shape parameter \(k\) of the Weibull distribution leads to a nonlinear equation that must be solved using numerical techniques.

5 Root Finiding of Nonlinear Equations

Consider a nonlinear equation of the form \(f(x) = 0\). Numerical methods for finding its roots can be broadly classified into two categories: those that utilize the gradient (the derivative \(f^\prime(x)\) and non-gradient methods that require only function evaluations. The secant method, a non-gradient approach, is demonstrated in the following animation.

Detailed discussion of numerical optimization is out of the scope of this class, we will use Brent’s hybrid method implemented in R to find the root of nonlinear equation. Brent method does not use derivatives. It is a hybrid algorithm that combines the bisection method, the secant method, and inverse quadratic interpolation. R function optimize() in package stats is the implementation of Brent’s method.

The following numerical example demonstrates the steps for find the shape parameter of Weibull model using Brent’s method.

# Set seed for reproducibility
set.seed(123)

# True parameters
true_shape <- 2.5
true_scale <- 3.0

# Generate Weibull distributed data
n <- 1000
x <- rweibull(n, shape = true_shape, scale = true_scale)

# Alternative approach using optim()
weibull_mom_optim <- function(x) {
  m1 <- mean(x)
  m2 <- mean(x^2)
  target <- m2 / (m1^2)
  
  # Objective function to minimize
  objective <- function(k) {
    gamma1 <- gamma(1 + 1/k)
    gamma2 <- gamma(1 + 2/k)
    (gamma2 / (gamma1^2) - target)^2
  }
  
  # Optimize for k using BRENT's Method
  opt <- optimize(objective, interval = c(0.1, 10))
  k_hat <- opt$minimum
  lambda_hat <- m1 / gamma(1 + 1/k_hat)
  
  return(list(shape = k_hat, scale = lambda_hat))
}

weibull_mom_optim(x)
$shape
[1] 2.519975

$scale
[1] 3.011203

The above numerical example simulated data from Weibull distribution with shape =2.5 and scale = 3. Next, we compare the estimated density (parametric), non-parametric kernel density, and true density.

# True parameters
true_shape <- 2.5
true_scale <- 3.0

# Create density plot comparing true distribution and estimated
x_range <- seq(0, max(x), length.out = 200)
true_dens <- dweibull(x_range, shape = true_shape, scale = true_scale)
mom_dens <- dweibull(x_range, shape = 2.52, scale = 3.0112)

## random sample
rand.sample <- rweibull(200, shape = true_shape, scale = true_scale)
d <- density(rand.sample)
pdf_interpolator <- approxfun(d$x, d$y)
##
plot_data <- data.frame(
  x = rep(x_range, 3),
  density = c(true_dens, mom_dens, pdf_interpolator(x_range)),
  Distribution = rep(c("True Density", "Method of Moments", "Sample Data (KDE)"), 
                    each = length(x_range))
)

weibull.plt <- ggplot(plot_data, aes(x = x, y = density, color = Distribution, linetype = Distribution)) +
  geom_line(size = 1) +
  labs(title = "Weibull Distribution: True vs Method of Moments Estimation",
       x = "Weibull Score", y = "True and Estimated Density") +
  theme_minimal() +
  scale_color_manual(values = c("True Density" = "red", "Method of Moments" = "blue", 
                               "Sample Data (KDE)" = "black")) +
  scale_linetype_manual(values = c("True Density" = "solid", "Method of Moments" = "dashed",
                                  "Sample Data (KDE)" = "dotted")) +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(weibull.plt)

Since the data was simulated from the Weibull population with shape 2.5 and scale 3. The MME of the shape and scale are very close to the true values. Therefore, the estimated parametric density curve is almost identical to the true density curve. The nonparametric kernel density curve is slightly different from the true density curve. This means that if the distribution is correctly specified, the parametric density estimation more efficient than the nonparametric kernel density estimation.

As a good practice, you can simulate a dataset from a Weibull distribution and attempt to fit a normal distribution to it. Plot the three resulting density curves—the true Weibull, the estimated normal, and a nonparametric kernel density—to compare the performance of parametric and nonparametric estimation methods.

LS0tDQp0aXRsZTogIk1ldGhvZCBvZiBNb21lbnQgRXN0aW1hdGlvbiAoTU1FKSINCmF1dGhvcjogIkNoZW5nIFBlbmciDQpkYXRlOiAiV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KDQojIyBsaWJyYXJ5KGxlYXBzKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCg0KXA0KDQoNCiMgSW50cm9kdWN0aW9uDQoNCkluIHN0YXRpc3RpY2FsIGluZmVyZW5jZSwgcG9pbnQgZXN0aW1hdGlvbiByZWZlcnMgdG8gdGhlIHByb2Nlc3Mgb2YgdXNpbmcgc2FtcGxlIGRhdGEgdG8gY2FsY3VsYXRlIGEgc2luZ2xlIHZhbHVlIChjYWxsZWQgYSAqKnBvaW50IGVzdGltYXRlKiopIHRoYXQgc2VydmVzIGFzIGEgImJlc3QgZ3Vlc3MiIG9yICJiZXN0IGVzdGltYXRlIiBvZiBhbiB1bmtub3duIHBvcHVsYXRpb24gcGFyYW1ldGVyLiBTb21lIHRlY2huaWNhbCB0ZXJtcw0KDQoqICoqUG9pbnQgZXN0aW1hdG9yKio6IEEgZnVuY3Rpb24gb2YgdGhlIHNhbXBsZSBkYXRhIHVzZWQgdG8gZXN0aW1hdGUgYW4gdW5rbm93biBwYXJhbWV0ZXIgJFx0aGV0YSQgb2YgYSBwb3B1bGF0aW9uLg0KDQoqICoqU3RhdGlzdGljKio6IEEgZnVuY3Rpb24gb2YgdGhlIHNhbXBsZSBkYXRhIG9ubHkgKG5vIHVua25vd24gcGFyYW1ldGVycykuDQoNCiogKipTYW1wbGUgc3BhY2UqKjogVGhlIHNldCBvZiBhbGwgcG9zc2libGUgc2FtcGxlcyAoZGF0YSBzZXRzKSB0aGF0IGNvdWxkIGJlIG9ic2VydmVkLg0KDQoqICoqUGFyYW1ldGVyIHNwYWNlKio6IFRoZSBzZXQgb2YgYWxsIHBvc3NpYmxlIHZhbHVlcyBvZiB0aGUgcGFyYW1ldGVyICRcdGhldGEkLg0KDQoNCkluIHRoZSBzdWJzZXF1ZW50IHNlY3Rpb25zLCB3ZSB3aWxsIGludHJvZHVjZSBzb21lIG5vdGF0aW9ucyBhbmQgZm9ybWFsaXplIHRoZSBhYm92ZSBjb25jZXB0cyBhcyB3ZWxsIGFzIHNvbWUgdGhlb3JpZXMgYWJvdXQgZXN0aW1hdGlvbnMgYW5kIGEgc3BlY2lhbCBwb2ludCBlc3RpbXRvciAtIG1ldGhvZCBvZiBtb21lbnQgKE1vTSkuDQoNCg0KIyAgQmFzaWNzIG9mIFBvaW50IEVzdGltYXRpb24NCg0KVGhpcyBzZWN0aW9uIHdpbGwgY292ZXIgdGhlIGNvcmUgY29uY2VwdHMgb2YgcG9pbnQgZXN0aW1hdGlvbiwgaW5jbHVkaW5nIHRoZSBjcml0ZXJpYSBmb3IgYSBnb29kIGVzdGltYXRvcuKAlHN1Y2ggYXMgdW5iaWFzZWRuZXNzLCBjb25zaXN0ZW5jeSwgYW5kIGVmZmljaWVuY3nigJRhbmQgaW50cm9kdWNlIGNvbW1vbiBtZXRob2RzIGZvciBkZXJpdmluZyB0aGVzZSBlc3RpbWF0ZXMsIGxpa2UgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24uIFVuZGVyc3RhbmRpbmcgdGhlc2UgYmFzaWNzIHByb3ZpZGVzIHRoZSBjcml0aWNhbCBmb3VuZGF0aW9uIGZvciBhbGwgc3Vic2VxdWVudCBzdGF0aXN0aWNhbCBpbmZlcmVuY2UsIGZyb20gY29uc3RydWN0aW5nIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHRvIHRlc3RpbmcgaHlwb3RoZXNlcy4NCg0KDQojIyBOb3RhdGlvbnMgYW5kIERlZmluaXRpb25zDQoNClRvIHN1bW1hcml6ZSB0aGUgYmFzaWMgcHJvcGVydGllcyBvZiBwb2ludCBlc3RpbWF0ZSBvZiBwb3B1bGF0aW9uIHBhcmFtZXRlcnMuIFdlIGludHJvZHVjZSBzb21lIG5vdGF0aW9ucy4gTGV0OiANCg0KKiAkWF8xLCBYXzIsIFxsZG90cywgWF9uJCBiZSBhIHJhbmRvbSBzYW1wbGUgZnJvbSBhIHBvcHVsYXRpb24gZGlzdHJpYnV0aW9uICRmKHh8XHRoZXRhKSQsIHdoZXJlICRcdGhldGEkIGlzIGFuIHVua25vd24gcGFyYW1ldGVyLiBJdCBpcyBvZnRlbiBkZW5vdGVkIGJ5ICRGX1x0aGV0YSh4KSQuDQoNCiogJFxUaGV0YSQgYmUgdGhlIHBhcmFtZXRlciBzcGFjZSAtIHBvc3NpYmxlIHZhbHVlcyBvZiAkXHRoZXRhJC4NCg0KKiAkXG1hdGhjYWx7WH0kIGJlIHRoZSBzYW1wbGUgc3BhY2UgLSBwb3NzaWJsZSB2YWx1ZXMgb2YgJHgkLg0KDQpBICoqc3RhdGlzdGljKiogaXMgYSBmdW5jdGlvbiAkVDogXG1hdGhjYWx7WH0gXHRvIFxtYXRoYmJ7Un1eayQgZm9yIHNvbWUgJGskIHRoYXQgZG9lcyBub3QgZGVwZW5kZW50IG9uICRcdGhldGEkDQoNCkEgKipwb2ludCBlc3RpbWF0b3IqKiAkXGhhdHtcdGhldGF9JCBvZiAkXHRoZXRhJCBpcyBhIHN0YXRpc3RpYyB3aG9zZSByYW5nZSAoKipwYXJhbWV0ZXIgc3BhY2UqKikgaXMgJFxUaGV0YSQgKG9yIGF0IGxlYXN0IGEgc3Vic2V0IG9mIGl0KSwgDQoNCiQkDQpcaGF0e1x0aGV0YX0gPSBUKFhfMSwgWF8yLCBcY2RvdHMsIFhfbikuDQokJA0KDQokJA0KXGhhdHtcdGhldGF9OiBcbWF0aGNhbHtYfSBcdG8gXFRoZXRhLCANCiQkDQp0aGF0IGlzLCBGb3IgYSBnaXZlbiBwb2ludCAkXG1hdGhiZntYfSA9IChYXzEsIFhfMiwgXGNkb3RzLCBYX24pJCBpbiBhIHNhbXBsZSBzcGFjZSAkXG1hdGhjYWx7WH0kOiAkXG1hdGhiYntYfSBcaW4gXG1hdGhjYWx7WH0kLA0KDQoNCiQkDQpcaGF0e1x0aGV0YX0oXG1hdGhiZntYfSkgXGluIFxUaGV0YQ0KJCQNCg0KYW5kICRcaGF0e1x0aGV0YX0kIGlzIGEgc3RhdGlzdGljLg0KDQoNCioqRXhhbXBsZSoqOiBTdXBwb3NlICRYXzEsIFhfMiwgXGNkb3RzLCBYX24gXHRvIE4oXG11LCBcc2lnbWFfMF4yKSQsICRcc2lnbWFfMF4yJCBpcyBhIGtub3duIHBvcHVsYXRpb24gdmFyaWFuY2UuIFdlIHdhbnQgdG8gZXN0aW1hdGUgJFxtdSBcaW4gXG1hdGhiYntSfSA9IFxUaGV0YSQuDQoNCiogJChYXzEsIFhfMiwgXGNkb3RzLCBYX24pIFxpbiBcbWF0aGJie1J9Xm4kLiBUaGF0IGlzLCAkbiQtZGltZW5zaW9uYWwgdmVjdG9yICQoWF8xLCBYXzIsIFxjZG90cywgWF9uKSQgaXMgYSBwb2ludCBpbiB0aGUgJG4kLWRpbWVuc2lvbmFsIHNwYWNlICRcbWF0aGJie1J9Xm4kLg0KDQoqIFBhcmFtZXRlciBzcGFjZSAkXFRoZXRhID0gXG1hdGhiYntSfSQuIFRoYXQgaXMsICRcbXUkIGlzIGEgcG9pbnQgaW4gdGhlIG9uZSBkaW1lbnNpb25hbCBzcGFjZSAkXG1hdGhiYntSfSQuDQoNCiogQSAqKnBvaW50IGVzdGltYXRvcioqICRcaGF0e1xtdX0oXG1hdGhiZntYfSkgPSBcYmFye1h9ID0gKFxzdW1fe2k9MX1ebiBYX2kpL24kLg0KDQpDbGVhcmx5LA0KDQoqICRcaGF0e1xtdX0kIGlzIGEgc3RhdGlzdGljIChkZXBlbmRzIG9ubHkgb24gc2FtcGxlKS4NCg0KKiAkXGhhdHtcbXV9OiBcbWF0aGJie1J9Xm5cZXF1aXYgXG1hdGhjYWx7WH0gIFx0byBcbWF0aGJie1J9IFxlcXVpdiAgXFRoZXRhJCBtYXBzIHNhbXBsZSBzcGFjZSB0byBwYXJhbWV0ZXIgc3BhY2UuDQoNClwNCg0KIyMgUHJvcGVydGllcyBvZiBQb2ludCBFc3RpbWF0ZQ0KDQoqKjEuIFVuYmlhc2VkbmVzcyoqDQoNCkFuIGVzdGltYXRvciAkXGhhdHtcdGhldGF9JCBpcyB1bmJpYXNlZCBpZiAkRVtcaGF0e1x0aGV0YX1dID0gXHRoZXRhJC4NCg0KVGhlIGJpYXMgb2YgYW4gZXN0aW1hdG9yIGlzIGRlZmluZWQgYXM6DQokJA0KXHRleHR7Qmlhc30oXGhhdHtcdGhldGF9KSA9IEUoXGhhdHtcdGhldGF9KSAtIFx0aGV0YQ0KJCQNCioqMi4gQ29uc2lzdGVuY3kqKg0KDQpBbiBlc3RpbWF0b3IgaXMgY29uc2lzdGVudCBpZjoNCg0KJCQNClxsaW1fe25cdG8gXGluZnR5fSBQKHxcaGF0e1x0aGV0YX0tXHRoZXRhfD5cZXBzaWxvbikgPSAwLCBcIFwgXHRleHR7IGZvciBhbGwgfSBcZXBzaWxvbiA+IDAuDQokJA0K4oGhDQoqKjMuIEVmZmljaWVuY3kqKg0KDQpBbW9uZyB1bmJpYXNlZCBlc3RpbWF0b3JzLCB0aGUgb25lIHdpdGggc21hbGxlciB2YXJpYW5jZSBpcyBtb3JlIGVmZmljaWVudC4gVGhlIENyYW3DqXItUmFvIGxvd2VyIGJvdW5kIGdpdmVzIHRoZSBtaW5pbXVtIHBvc3NpYmxlIHZhcmlhbmNlIGZvciBhbiB1bmJpYXNlZCBlc3RpbWF0b3I6DQoNCiQkDQpcdGV4dHtWYXJ9KFxoYXR7XHRoZXRhfSkgXGdlIFxmcmFjezF9e0lfbihcdGhldGEpfT1cZnJhY3sxfXtuSV8wKFx0aGV0YSl9DQokJA0KDQp3aGVyZSAkSV8wKFx0aGV0YSkkIGlzIHRoZSAqKkZpc2hlciBpbmZvcm1hdGlvbioqIHRoYXQgbWVhc3VyZXMgdGhlIGFtb3VudCBvZiBpbmZvcm1hdGlvbiB0aGF0IGEgc2FtcGxlICRce1hcfSQgY2FycmllcyBhYm91dCB0aGUgdW5rbm93biBwb3B1bGF0aW9uIHBhcmFtZXRlciAkXHRoZXRhJCB0byBiZSBlc3RpbWF0ZWQuIFRvIGNhbGN1bGF0ZSB0aGUgRmlzaGVyIEluZm9ybWF0aW9uIG9mIGEgdW5pdmFyaWF0ZSBwYXJhbWV0ZXIsIHdlIG9ubHkgbmVlZCB0byBmaW5kIHRoZSBuZWdhdGl2ZSBleHBlY3RlZCB2YWx1ZSBvZiB0aGUgMm5kIG9yZGVyIGRlcml2YXRpdmUgb2YgdGhlIGxvZyBkZW5zaXR5IGZ1bmN0aW9uIChjb250aW51b3VzIFJWKSBvciBtYXNzIGZ1bmN0aW9uIChmb3IgZGlzY3JldGUgUlYpIGFzIGZvbGxvd3MNCg0KJCQNCklfMChcdGhldGEpID0gLUVfWFxsZWZ0WyBcZnJhY3tkXjJ9e2RcdGhldGFeMn0gXGxvZyBmKFg6IFx0aGV0YSlccmlnaHRdDQokJA0KDQoqKkV4YW1wbGUqKjogQ29uc2lkZXIgUG9pc3NvbiBkaXN0cmlidXRpb24gDQoNCiQkDQpQKFg9aykgPSBcZnJhY3tcbGFtYmRhXmsgZV57LVxsYW1iZGF9fXtrIX0sIFwgXCBcbGFtYmRhID0gMCwgMSwgMiwgXGNkb3RzDQokJA0KDQpCYXNlZCBvbiB0aGUgYWJvdmUgZGVmaW5pdGlvbiBvZiB0aGUgRmlzaGVyIEluZm9ybWF0aW9uIG9mICRcbGFtYmRhJCwgd2UgY2FsY3VsYXRlICRJXzAoXGxhbWJkYSkkIGluIHRoZSBmb2xsb3dpbmcgc3RlcHMNCg0KMS4gTGV0ICRMKFxsYW1iZGEpID0gZihYOlxsYW1iZGEpID0gXGxhbWJkYV5YIGVeey1cbGFtYmRhfS9YISQNCg0KMi4gJFxlbGwoXGxhbWJkYSkgPSBcbG9nIEwoXGxhbWJkYSkgPSAtXGxhbWJkYSArIFhcbG9nKFxsYW1iZGEpIC0gXGxvZyhYISkkDQoNCjMuIFRha2luZyB0aGUgZmlyc3Qgb3JkZXIgZGVyaXZhdGl2ZSAkXGVsbChcbGFtYmRhKSQsIHdlIGdldCAkXGVsbF5ccHJpbWUoXGxhbWJkYSkgPSAtMSArIFgvXGxhbWJkYSQuDQoNCjQuIFRha2luZyB0aGUgc2Vjb25kIG9yZGVyIGRlcml2ZXRpdmUgJFxlbGwoXGxhbWJkYSkkLCB3ZSBnZXQgJFxlbGxee1xwcmltZVxwcmltZX0oXGxhbWJkYSkgPSAteC9cbGFtYmRhXjIkDQoNCjUuICRJXzAoXGxhbWJkYSkgPSAtRV9YW1xlbGxee1xwcmltZVxwcmltZX0oXGxhbWJkYSldID0gLUVfWFstWC9cbGFtYmRhXjJdID0gRV9YW1hdL1xsYW1iZGFeMiA9IDEvXGxhbWJkYSQuDQoNCg0KDQoNCg0KDQoqKjQuIE1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSoqDQoNClRoZSBNU0UgY29tYmluZXMgYm90aCB2YXJpYW5jZSBhbmQgYmlhczoNCg0KJCQNCk1TRShcaGF0e1x0aGV0YX0pID0gRVsoXGhhdHtcdGhldGF9IC0gXHRoZXRhKV4yXSA9IFx0ZXh0e1Zhcn0oXGhhdHtcdGhldGF9KSArIFtcdGV4dHtCaWFzfShcaGF0e1x0aGV0YX0pXV4yDQokJA0KDQoNCg0KDQoNCg0KDQojIE1ldGhvZCBvZiBNb21lbnRzIEVzdGltYXRpb24NCg0KVGhlIE1ldGhvZCBvZiBNb21lbnRzIChNb00pIGlzIG9uZSBvZiB0aGUgb2xkZXN0IGFuZCBtb3N0IGludHVpdGl2ZSBhcHByb2FjaGVzIHRvIHBhcmFtZXRlciBlc3RpbWF0aW9uLiBUaGUgYmFzaWMgaWRlYSBpcyB0byBlcXVhdGUgcG9wdWxhdGlvbiBtb21lbnRzIHdpdGggc2FtcGxlIG1vbWVudHMgYW5kIHNvbHZlIGZvciB0aGUgcGFyYW1ldGVycy4NCg0KIyMgUG9wdWxhdGlvbiBhbmQgU2FtcGxlIE1vbWVudHMNCg0KUmVjYWxsIHRoYXQgdGhlICRrJC10aCBwb3B1bGF0aW9uIG1vbWVudCBhYm91dCB0aGUgb3JpZ2luIGlzDQoNCiQkDQpcbXVeaz1FW1hea10uIA0KJCQNCg0KQ2xlYXJseSwgdGhlICRrJC10aCBtb21lbnQgaXMgYSBmdW5jdGlvbiBvZiBwb3B1bGF0aW9uIHBhcmFtZXRlcnMgb25seS4gSXQgaXMgaW5kZXBlbmRlbnQgb24gdGhlIG9ic2VydmVkIGRhdGEuDQoNCk9uIHRoZSB0aGUgJGskLXRoIHNhbXBsZSBtb21lbnQgaXM6DQoNCiQkDQptX2sgPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ebiBYX2leaw0KJCQNCg0KVGhlIHRoZW9yZXRpY2FsIG1vbWVudHMgY2FuIGJlIGRlcml2ZWQgZnJvbSB0aGUgbW9tZW50IGdlbmVyYXRpbmcgZnVuY3Rpb24gb2YgYSBzcGVjaWZpZWQgbW9kZWwgKHBhcmFtZXRlcmljIGRpc3RyaWJ1dGlvbikuDQoNCg0KIyMgUHJvY2VkdXJlIGZvciBNZXRob2Qgb2YgTW9tZW50IEVzdGltYXRpb24NCg0KVGhlIGZ1bmRhbWVudGFsIGxvZ2ljIG9mIHRoZSBtb21lbnQgZXN0aW1hdGlvbiBpcyB0byAqKm1ha2UgdGhlIHByb3BlcnRpZXMgb2YgdGhlIHNhbXBsZSBtYXRjaCB0aGUgcHJvcGVydGllcyBvZiB0aGUgdGhlb3JldGljYWwgcHJvYmFiaWxpdHkgbW9kZWwqKi4gU2luY2UgdGhlIHRoZW9yZXRpY2FsIG1vZGVsJ3MgcHJvcGVydGllcyAobGlrZSBtZWFuLCB2YXJpYW5jZSkgZGVwZW5kIG9uIGl0cyB1bmtub3duIHBhcmFtZXRlcnMsIHdlIGNhbiBzZXQgdXAgZXF1YXRpb25zIHRvIHNvbHZlIGZvciB0aG9zZSBwYXJhbWV0ZXJzLiBUaGlzIGxvZ2ljIGlzIGEgc3RyYWlnaHRmb3J3YXJkIGFwcGxpY2F0aW9uIG9mIHRoZSAqKmFuYWxvZ3kgcHJpbmNpcGxlKio6IDxmb250IGNvbG9yID0gInJlZCI+KippZiB0aGUgbW9kZWwgaXMgY29ycmVjdCwgdGhlbiB0aGUgc2FtcGxlIHNob3VsZCByZWZsZWN0IGl0LioqPC9mb250Pg0KDQoNCioqRXN0aW1hdGlvbiBQcm9jZWR1cmUqKg0KDQpGb3IgYSBkaXN0cmlidXRpb24gd2l0aCAkcCQgcGFyYW1ldGVycyAkXHRoZXRhXzEsIFx0aGV0YV8yLCBcbGRvdHMsIFx0aGV0YV9wJDoNCg0KMS4gRXhwcmVzcyBwb3B1bGF0aW9uIG1vbWVudHMgaW4gdGVybXMgb2YgcGFyYW1ldGVycyAtICRrJC10aCB0aGVvcmV0aWNhbCBtb21lbnQ6DQoNCiQkDQpcbXVfayA9IGhfayhcdGhldGFfMSwgXHRoZXRhXzIsIFxjZG90cywgXHRoZXRhX3ApDQokJA0KDQpmb3IgJGsgPSAxLCAyLCBcY2RvdHMsIHAkIGFyZSBwbw0KDQoNCjIuIEVxdWF0ZSBwb3B1bGF0aW9uIG1vbWVudHMgd2l0aCBzYW1wbGUgbW9tZW50czoNCg0KJCQNCmhfayhcdGhldGFfMSwgXHRoZXRhXzIsIFxjZG90cywgXHRoZXRhX3ApID0gbV9rDQokJA0KZm9yICRrPTEsMixcY2RvdHMscCQNCg0KMy4gU29sdmUgdGhlIHN5c3RlbSBvZiBlcXVhdGlvbnMgdG8gb2J0YWluIE1vTSBlc3RpbWF0b3JzICRcaGF0e1x0aGV0YX1fMSwgXGhhdHtcdGhldGF9XzIsIFxsZG90cywgXGhhdHtcdGhldGF9X3AkDQoNClRvIGV4cGxhaW4gdGhlIGNvbXB1dGluZyBlZmZvcnRzLCB3ZSByZS1leHByZXNzIHRoZSBhYm92ZSBzeXN0ZW0gb2YgJHAkIGVxdWF0aW9ucyBleHBsaWNpdGx5IGluIHRoZSBmb2xsb3dpbmcNCg0KDQokJA0KXGJlZ2lue2FsaWduKn0NClxtdV8xKFx0aGV0YV8xLCBcZG90cywgXHRoZXRhX3ApICY9IG1fMSBcXA0KXG11XzIoXHRoZXRhXzEsIFxkb3RzLCBcdGhldGFfcCkgJj0gbV8yIFxcDQomXHZkb3RzIFxcDQpcbXVfcChcdGhldGFfMSwgXGRvdHMsIFx0aGV0YV9wKSAmPSBtX3ANClxlbmR7YWxpZ24qfQ0KJCQNCg0KSW4gZ2VuZXJhbCwgdGhlIGFib3ZlIGVxdWF0aW9ucyBhcmUgbm9ubGluZWFyLiBUaGlzIG1lYW5zIHRoYXQgbnVtZXJpY2FsIG1ldGhvZHMgYXJlIHJlcXVpcmVkIHRvIHNvbHZlIHRoZSBzeXN0ZW0gb2YgZXF1YXRpb25zLiAgSW4gdGhlIG5leHQgc2VjdGlvbiwgd2Ugd2lsbCB1c2Ugc2V2ZXJhbCBleGFtcGxlcyB0byBzaG93IGhvdyB0byBtb21lbnQgb2YgZXN0aW1hdGlvbiBiYXNlZCBvbiBzb21lIHNwZWNpYWwgbW9kZWxzIGxlYXJuZWQgaW4gdGhlIHByZXZpb3VzIGNsYXNzLg0KDQoNCiMgRXhhbXBsZXMgb2YgTWV0aG9kIG9mIE1vbWVudHMgRXN0aW1hdGlvbg0KDQpUaGlzIHNlY3Rpb24gZm9jdXNlcyBvbiB0aHJlZSBleGFtcGxlcyB1c2luZyB3ZWxsLWtub3duIG1vZGVscy4NCg0KDQojIyBFeGFtcGxlIDE6IE5vcm1hbCBEaXN0cmlidXRpb24NCg0KQ29uc2lkZXIgJFx7WF8xLCBYXzIsIFxjZG90cywgWF9uIFx9IFxzaW0gTihcbXUsIFxzaWdtYV4yKSQsIHdlIHdpbGwgdXNlIG1ldGhvZCBvZiBtb21lbnQgdG8gZXN0aW1hdGUgdGhlIHR3byBwYXJhbWV0ZXJzICRcdGhldGEgPSAoXG11LCBcc2lnbWFeMikkLg0KDQpTaW5jZSB0aGVyZSBhcmUgdHdvIHBhcmFtZXRlcnMgaW4gdGhlIG1vZGVsLCB3ZSBuZWVkIHRvIGNhbGN1bGF0ZSB0aGUgKipmaXJzdCBhbmQgc2Vjb25kIHBvcHVsYXRpb24gbW9tZW50cyoqIGFuZCB0aGUgY29ycmVzcG9uZGluZyBzYW1wbGUgbW9tZW50cyBhcyBmb2xsb3dzLg0KDQoqIFBvcHVsYXRpb24gbW9tZW50cyBhcmUgY2FsY3VsYXRlZCBpbiB0aGUgZm9sbG93aW5nOg0KDQokJA0KXGJlZ2lue2FsaWduZWR9DQpcbXVfMSAmPSBFW1hdID0gXG11IFxcDQpcbXVfMiAmPSBFW1heMl0gPSBcc2lnbWFeMiArIFxtdV4yDQpcZW5ke2FsaWduZWR9DQokJA0KDQoqIFNhbXBsZSBtb21lbnRzOg0KDQokJA0KXGJlZ2lue2FsaWduZWR9DQptXzEgJj0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIFhfaSBcXA0KbV8yICY9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ebiBYX2leMg0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KIFRoZSBtZXRob2Qgb2YgbW9tZW50IGVzdGltYXRvciBpcyB0aGUgc29sdXRpb24gdG8gdGhlIGZvbGxvd2luZyBzeXN0ZW0gb2YgZXF1YXRpb25zDQogDQogJCQNClxiZWdpbnthbGlnbmVkfQ0KXG11ICY9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ebiBYX2kgXFwNClxzaWdtYV4yICsgXG11XjIgJj0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIFhfaV4yDQpcZW5ke2FsaWduZWR9DQokJA0KIA0KIFNvbHZlaW5nIHRoZSBhYm92ZSBzeXN0ZW0gb2Ygbm9ubGluZWFyIGVxdWF0aW9ucywgd2UgaGF2ZQ0KIA0KICQkDQogXGJlZ2lue2FsaWduKn0NClxoYXR7XG11fSAmPSBcZnJhY3sxfXtufSBcc3VtX3tpPTF9Xm4gWF9pICYgPSBcYmFye1h9IFxcDQpcaGF0e1xzaWdtYX1eMiAgJj0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIFhfaV4yIC0gXGJhcntYfV4yICY9IFxmcmFjezF9e259XHN1bV97aT0xfV5uKFhfaS1cYmFye1h9KV4yDQpcZW5ke2FsaWduKn0NCiAkJA0KIA0KIE5leHQsIHdlIGltcGxlbWVudCB0aGUgYWJvdmUgTU1FIHRocm91Z2ggYSBzaW11bGF0ZWQgZGF0YSBpbiBSLg0KIA0KYGBge3J9DQojIEV4YW1wbGU6IE1vTSBmb3IgTm9ybWFsIERpc3RyaWJ1dGlvbg0Kc2V0LnNlZWQoMTIzKQ0KbiA8LSAxMDAwDQp0cnVlX211IDwtIDUNCnRydWVfc2lnbWEgPC0gMg0KDQojIEdlbmVyYXRlIHNhbXBsZSBkYXRhDQpzYW1wbGVfZGF0YSA8LSBybm9ybShuLCBtZWFuID0gdHJ1ZV9tdSwgc2QgPSB0cnVlX3NpZ21hKQ0KDQojIE1ldGhvZCBvZiBNb21lbnRzIGVzdGltYXRpb24NCm1vbV9tdSA8LSBtZWFuKHNhbXBsZV9kYXRhKQ0KbW9tX3NpZ21hX3NxIDwtIG1lYW4oc2FtcGxlX2RhdGFeMikgLSBtb21fbXVeMg0KbW9tX3NpZ21hIDwtIHNxcnQobW9tX3NpZ21hX3NxKQ0KDQpjYXQoIlRydWUgcGFyYW1ldGVyczogzrwgPSIsIHRydWVfbXUsICIsIM+DID0iLCB0cnVlX3NpZ21hLCAiXG4iKQ0KY2F0KCJNb00gZXN0aW1hdGVzOiDOvF9oYXQgPSIsIHJvdW5kKG1vbV9tdSwgMyksIA0KICAgICIsIM+DX2hhdCA9Iiwgcm91bmQobW9tX3NpZ21hLCAzKSwgIlxuIikNCmBgYA0KDQoNCg0KIyMgRXhhbXBsZSAyOiBHYW1tYSBEaXN0cmlidXRpb24NCg0KDQpGb3IgJFggXHNpbSBcdGV4dHtHYW1tYX0oXGFscGhhLCBcYmV0YSkkLCB3aXRoIFBERjoNCg0KJCQNCmYoeCBcbWlkIFxhbHBoYSwgXGJldGEpID0gXGZyYWN7XGJldGFee1xhbHBoYX19e1xHYW1tYShcYWxwaGEpfSB4XntcYWxwaGEgLSAxfSBlXnstXGJldGEgeH0gXHF1YWQgXHRleHR7Zm9yIH0geCA+IDANCiQkDQoNCg0KV2Uga25vdyB0aGF0IHRoZSB0b3AgcG9wdWxhdGlvbiBtb21lbnRzIGFyZSBnaXZlbiBpbiB0aGUgZm9sbG93aW5nDQoNCiQkDQpcYmVnaW57YWxpZ24qfQ0KXG11XzEgJj0gRVtYXSA9IFxmcmFje1xhbHBoYX17XGJldGF9IFxcWzJtbV0NClxtdV8yICY9IEVbWF4yXSA9IFxmcmFje1xhbHBoYShcYWxwaGEgKyAxKX17XGJldGFeMn0NClxlbmR7YWxpZ24qfQ0KJCQNCg0KQXNzdW1lIHRoZSBmaXJzdCBhbmQgc2Vjb25kIG1vbWVudHMgdG8gYmUgJG1fMSQgYW5kICRtXzIkLiBXZSBzZXQgdXAgdGhlIGZvbGxvd2luZyBzeXN0ZW0gb2YgZXF1YXRpb25zDQoNCiQkDQpcYmVnaW57YWxpZ24qfQ0KbV8xICYgPSBcZnJhY3tcYWxwaGF9e1xiZXRhfSBcXFsybW1dDQptXzIgJiA9IFxmcmFje1xhbHBoYShcYWxwaGEgKyAxKX17XGJldGFeMn0NClxlbmR7YWxpZ24qfQ0KJCQNCg0KDQpTb2x2aW5nIGZvciBwYXJhbWV0ZXJzICRcYWxwaGEkIGFuZCAkXGJldGEkIGZyb20gdGhlIGFib3ZlIHN5c3RlbSBvZiBlcXVhdGlvbiB0byBnZXQgdGhlIHRoZSBlc3RpbWF0b3JzIGJhc2VkIG9uIHRoZSBtZXRob2Qgb2YgbW9tZW50IGVzdGltYXRpb246DQoNCiQkDQpcYmVnaW57YWxpZ24qfQ0KXGhhdHtcYmV0YX0gJj0gXGZyYWN7bV8xfXttXzIgLSBtXzFeMn0gXFxbMm1tXQ0KXGhhdHtcYWxwaGF9ICY9IG1fMSBcaGF0e1xiZXRhfSA9IFxmcmFje21fMV4yfXttXzIgLSBtXzFeMn0NClxlbmR7YWxpZ24qfQ0KJCQNCiANCiANClRoZSBmb2xsb3dpbmcgaXMgdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBhYm92ZSBNTUUgdGhyb3VnaCBhIHNpbXVsYXRlZCBkYXRhIGluIFIuDQogDQoNCmBgYHtyfQ0KIyBFeGFtcGxlOiBNb00gZm9yIEdhbW1hIERpc3RyaWJ1dGlvbg0Kc2V0LnNlZWQoMTIzKQ0KbiA8LSAxMDAwDQp0cnVlX2FscGhhIDwtIDMNCnRydWVfYmV0YSA8LSAyDQoNCiMgR2VuZXJhdGUgc2FtcGxlIGRhdGENCnNhbXBsZV9nYW1tYSA8LSByZ2FtbWEobiwgc2hhcGUgPSB0cnVlX2FscGhhLCByYXRlID0gdHJ1ZV9iZXRhKQ0KDQojIE1ldGhvZCBvZiBNb21lbnRzIGVzdGltYXRpb24NCm0xIDwtIG1lYW4oc2FtcGxlX2dhbW1hKQ0KbTIgPC0gbWVhbihzYW1wbGVfZ2FtbWFeMikNCg0KbW9tX2JldGEgPC0gbTEgLyAobTIgLSBtMV4yKQ0KbW9tX2FscGhhIDwtIG0xICogbW9tX2JldGENCg0KY2F0KCJUcnVlIHBhcmFtZXRlcnM6IM6xID0iLCB0cnVlX2FscGhhLCAiLCDOsiA9IiwgdHJ1ZV9iZXRhLCAiXG4iKQ0KY2F0KCJNb00gZXN0aW1hdGVzOiDOsV9oYXQgPSIsIHJvdW5kKG1vbV9hbHBoYSwgMyksIA0KICAgICIsIM6yX2hhdCA9Iiwgcm91bmQobW9tX2JldGEsIDMpLCAiXG4iKQ0KYGBgDQoNCg0KDQoqKkV4YW1wbGUgMy4gV2VpYnVsbCBEaXN0cmlidXRpb24qKg0KDQpUaGUgV2VpYnVsbCBkaXN0cmlidXRpb24gaGFzIHByb2JhYmlsaXR5IGRlbnNpdHkgZnVuY3Rpb246DQoNCiQkDQpmKHggXG1pZCBcbGFtYmRhLCBrKSA9IFxmcmFje2t9e1xsYW1iZGF9IFxsZWZ0KCBcZnJhY3t4fXtcbGFtYmRhfSBccmlnaHQpXntrLTF9IGVeey0oeC9cbGFtYmRhKV5rfSBccXVhZCBcdGV4dHtmb3IgfSB4IFxnZXEgMA0KJCQNCg0KDQp3aGVyZQ0KDQoqICRrPjAkIGlzIHRoZSBzaGFwZSBwYXJhbWV0ZXINCg0KKiAkXGxhbWJkYSA+IDAkIGlzIHRoZSBzY2FsZSBwYXJhbWV0ZXINCg0KVGhlIGZpcnN0IGFuZCBzZWNvbmQgbW9tZW50cyBvZiBwb3B1bGF0aW9uIGFyZQ0KDQokJA0KXGJlZ2lue2FsaWduKn0NClxtdV8xICY9IEVbWF0gPSBcbGFtYmRhIFxHYW1tYVxsZWZ0KDEgKyBcZnJhY3sxfXtrfVxyaWdodCkgXFwNClxtdV8yICY9IEVbWF4yXSA9IFxsYW1iZGFeMiBcR2FtbWFcbGVmdCgxICsgXGZyYWN7Mn17a31ccmlnaHQpDQpcZW5ke2FsaWduKn0NCiQkDQoNClRoZSBjb3JyZXNwb25kaW5nIHNhbXBsZSBtb21lbnRzIGFyZQ0KDQokJA0KXGJlZ2lue2FsaWduKn0NCm1fMSAmPSBcZnJhY3sxfXtufSBcc3VtX3tpPTF9Xm4gWF9pIFxcDQptXzIgJj0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIFhfaV4yDQpcZW5ke2FsaWduKn0NCiQkDQoNCg0KV2Ugc2V0IHBvcHVsYXRpb24gbW9tZW50cyBlcXVhbCB0byBzYW1wbGUgbW9tZW50cyB0byB0aGUgZm9sbG93aW5nIE1ldGhvZCBvZiBNb21lbnRzIEVxdWF0aW9uczoNCg0KJCQNClxiZWdpbnthbGlnbip9DQpcbGFtYmRhIFxHYW1tYVxsZWZ0KDEgKyBcZnJhY3sxfXtrfVxyaWdodCkgJj0gbV8xIFxxdWFkIFxjZG90c1xjZG90c1xxdWFkXHRleHR7KDEpfVxcDQpcbGFtYmRhXjIgXEdhbW1hXGxlZnQoMSArIFxmcmFjezJ9e2t9XHJpZ2h0KSAmPSBtXzIgXHF1YWQgXGNkb3RzXGNkb3RzXHF1YWRcdGV4dHsoMil9DQpcZW5ke2FsaWduKn0NCiQkDQoNClRoZSBhYm92ZSBzeXN0ZW0gb2YgZXF1YXRpb25zIGRvZXMgbm90IGhhdmUgYSBjbG9zZWQgZm9ybSBzb2x1dGlvbi4gV2UgbmV4dCBza2V0Y2ggdGhlIHN0ZXBzIGZvciBzb2x2aW5nIHRoZSBhYm92ZSBub25saW5lYXIgc3lzdGVtLiANCg0KRnJvbSBlcXVhdGlvbnMgKDEpIGFuZCAoMiksIHdlIGNhbiBlbGltaW5hdGUgJFxsYW1iZGEkOg0KDQoNCioqU3RlcCAxKio6IFNxdWFyZSBlcXVhdGlvbiAoMSk6DQoNCiQkDQpcbGFtYmRhXjIgXGxlZnRbXEdhbW1hXGxlZnQoMSArIFxmcmFjezF9e2t9XHJpZ2h0KVxyaWdodF1eMiA9IG1fMV4yDQokJA0KDQoqKlN0ZXAgMioqOiBEaXZpZGUgZXF1YXRpb24gKDIpIGJ5IHRoaXMgcmVzdWx0Og0KDQokJA0KXGZyYWN7XEdhbW1hXGxlZnQoMSArIFxmcmFjezJ9e2t9XHJpZ2h0KX17XGxlZnRbXEdhbW1hXGxlZnQoMSArIFxmcmFjezF9e2t9XHJpZ2h0KVxyaWdodF1eMn0gPSBcZnJhY3ttXzJ9e21fMV4yfQ0KJCQNCg0KKipTdGVwIDMqKjogTGV0ICRcaGF0e2t9JCBiZSB0aGUgc29sdXRpb24gdG86DQogIA0KJCQNClxmcmFje1xHYW1tYVxsZWZ0KDEgKyBcZnJhY3syfXtrfVxyaWdodCl9e1xsZWZ0W1xHYW1tYVxsZWZ0KDEgKyBcZnJhY3sxfXtrfVxyaWdodClccmlnaHRdXjJ9ID0gXGZyYWN7bV8yfXttXzFeMn0NCiQkDQoNCioqU3RlcCA0Kio6IE9uY2UgJFxsYW1iZGEkIGlzIGZvdW5kLCBvYnRhaW4gJFxoYXR7XGxhbWJkYX0kICBmcm9tOg0KDQokJA0KXGhhdHtcbGFtYmRhfSA9IFxmcmFje21fMX17XEdhbW1hXGxlZnQoMSArIFxmcmFjezF9e1xoYXR7a319XHJpZ2h0KX0NCiQkDQoNClRoZSBwYXJhbWV0ZXIgJGskIGNhbiBiZSBzb2x2ZWQgbnVtZXJpY2FsbHkgZnJvbSB0aGUgZm9sbG93aW5nIGVxdWF0aW9uOg0KDQoNCiQkDQpnKGspID0gXGZyYWN7XEdhbW1hXGxlZnQoMSArIFxmcmFjezJ9e2t9XHJpZ2h0KX17XGxlZnRbXEdhbW1hXGxlZnQoMSArIFxmcmFjezF9e2t9XHJpZ2h0KVxyaWdodF1eMn0gLSBcZnJhY3ttXzJ9e21fMV4yfSA9IDANCiQkDQoNClRoZSBtZXRob2Qgb2YgbW9tZW50cyBlc3RpbWF0aW9uIGZvciB0aGUgc2hhcGUgcGFyYW1ldGVyICRrJCBvZiB0aGUgV2VpYnVsbCBkaXN0cmlidXRpb24gbGVhZHMgdG8gYSBub25saW5lYXIgZXF1YXRpb24gdGhhdCBtdXN0IGJlIHNvbHZlZCB1c2luZyBudW1lcmljYWwgdGVjaG5pcXVlcy4NCg0KDQojIFJvb3QgRmluaWRpbmcgb2YgTm9ubGluZWFyIEVxdWF0aW9ucw0KDQpDb25zaWRlciBhIG5vbmxpbmVhciBlcXVhdGlvbiBvZiB0aGUgZm9ybSAkZih4KSA9IDAkLiBOdW1lcmljYWwgbWV0aG9kcyBmb3IgZmluZGluZyBpdHMgcm9vdHMgY2FuIGJlIGJyb2FkbHkgY2xhc3NpZmllZCBpbnRvIHR3byBjYXRlZ29yaWVzOiB0aG9zZSB0aGF0IHV0aWxpemUgdGhlIGdyYWRpZW50ICh0aGUgZGVyaXZhdGl2ZSAkZl5ccHJpbWUoeCkkIGFuZCBub24tZ3JhZGllbnQgbWV0aG9kcyB0aGF0IHJlcXVpcmUgb25seSBmdW5jdGlvbiBldmFsdWF0aW9ucy4gVGhlIHNlY2FudCBtZXRob2QsIGEgbm9uLWdyYWRpZW50IGFwcHJvYWNoLCBpcyBkZW1vbnN0cmF0ZWQgaW4gdGhlIGZvbGxvd2luZyBhbmltYXRpb24uDQoNCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIiwgIG91dC53aWR0aCA9ICc2NSUnfQ0KI2lmIChrbml0cjo6OmlzX2xhdGV4X291dHB1dCgpKSB7DQojICBrbml0cjo6YXNpc19vdXRwdXQoJ1xcdXJse2h0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9NQVQzMjUvcmF3L21haW4vdzAzL2ltZy93MDMtYmlzZWN0aW9uTWV0aG9kLmdpZn0nKQ0KI30gZWxzZSB7DQojICBrbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaW1nL3cwMy1iaXNlY3Rpb25NZXRob2QuZ2lmIikNCiN9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiTWV0b2RvX2RlbGxlX3NlY2FudGkuZ2lmIikNCmBgYA0KRGV0YWlsZWQgZGlzY3Vzc2lvbiBvZiBudW1lcmljYWwgb3B0aW1pemF0aW9uIGlzIG91dCBvZiB0aGUgc2NvcGUgb2YgdGhpcyBjbGFzcywgd2Ugd2lsbCB1c2UgQnJlbnQncyBoeWJyaWQgbWV0aG9kIGltcGxlbWVudGVkIGluIFIgdG8gZmluZCB0aGUgcm9vdCBvZiBub25saW5lYXIgZXF1YXRpb24uIEJyZW50IG1ldGhvZCBkb2VzIG5vdCB1c2UgZGVyaXZhdGl2ZXMuIEl0IGlzIGEgaHlicmlkIGFsZ29yaXRobSB0aGF0IGNvbWJpbmVzIHRoZSBiaXNlY3Rpb24gbWV0aG9kLCB0aGUgc2VjYW50IG1ldGhvZCwgYW5kIGludmVyc2UgcXVhZHJhdGljIGludGVycG9sYXRpb24uIFIgZnVuY3Rpb24gYG9wdGltaXplKClgIGluIHBhY2thZ2UgKipzdGF0cyoqIGlzIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBCcmVudCdzIG1ldGhvZC4NCg0KVGhlIGZvbGxvd2luZyBudW1lcmljYWwgZXhhbXBsZSBkZW1vbnN0cmF0ZXMgdGhlIHN0ZXBzIGZvciBmaW5kIHRoZSBzaGFwZSBwYXJhbWV0ZXIgb2YgV2VpYnVsbCBtb2RlbCB1c2luZyBCcmVudCdzIG1ldGhvZC4gDQoNCg0KYGBge3J9DQojIFNldCBzZWVkIGZvciByZXByb2R1Y2liaWxpdHkNCnNldC5zZWVkKDEyMykNCg0KIyBUcnVlIHBhcmFtZXRlcnMNCnRydWVfc2hhcGUgPC0gMi41DQp0cnVlX3NjYWxlIDwtIDMuMA0KDQojIEdlbmVyYXRlIFdlaWJ1bGwgZGlzdHJpYnV0ZWQgZGF0YQ0KbiA8LSAxMDAwDQp4IDwtIHJ3ZWlidWxsKG4sIHNoYXBlID0gdHJ1ZV9zaGFwZSwgc2NhbGUgPSB0cnVlX3NjYWxlKQ0KDQojIEFsdGVybmF0aXZlIGFwcHJvYWNoIHVzaW5nIG9wdGltKCkNCndlaWJ1bGxfbW9tX29wdGltIDwtIGZ1bmN0aW9uKHgpIHsNCiAgbTEgPC0gbWVhbih4KQ0KICBtMiA8LSBtZWFuKHheMikNCiAgdGFyZ2V0IDwtIG0yIC8gKG0xXjIpDQogIA0KICAjIE9iamVjdGl2ZSBmdW5jdGlvbiB0byBtaW5pbWl6ZQ0KICBvYmplY3RpdmUgPC0gZnVuY3Rpb24oaykgew0KICAgIGdhbW1hMSA8LSBnYW1tYSgxICsgMS9rKQ0KICAgIGdhbW1hMiA8LSBnYW1tYSgxICsgMi9rKQ0KICAgIChnYW1tYTIgLyAoZ2FtbWExXjIpIC0gdGFyZ2V0KV4yDQogIH0NCiAgDQogICMgT3B0aW1pemUgZm9yIGsgdXNpbmcgQlJFTlQncyBNZXRob2QNCiAgb3B0IDwtIG9wdGltaXplKG9iamVjdGl2ZSwgaW50ZXJ2YWwgPSBjKDAuMSwgMTApKQ0KICBrX2hhdCA8LSBvcHQkbWluaW11bQ0KICBsYW1iZGFfaGF0IDwtIG0xIC8gZ2FtbWEoMSArIDEva19oYXQpDQogIA0KICByZXR1cm4obGlzdChzaGFwZSA9IGtfaGF0LCBzY2FsZSA9IGxhbWJkYV9oYXQpKQ0KfQ0KDQp3ZWlidWxsX21vbV9vcHRpbSh4KQ0KYGBgDQoNClRoZSBhYm92ZSBudW1lcmljYWwgZXhhbXBsZSBzaW11bGF0ZWQgZGF0YSBmcm9tIFdlaWJ1bGwgZGlzdHJpYnV0aW9uIHdpdGggc2hhcGUgPTIuNSBhbmQgc2NhbGUgPSAzLiBOZXh0LCB3ZSBjb21wYXJlIHRoZSBlc3RpbWF0ZWQgZGVuc2l0eSAocGFyYW1ldHJpYyksIG5vbi1wYXJhbWV0cmljIGtlcm5lbCBkZW5zaXR5LCBhbmQgdHJ1ZSBkZW5zaXR5LiANCg0KDQpgYGB7cn0NCiMgVHJ1ZSBwYXJhbWV0ZXJzDQp0cnVlX3NoYXBlIDwtIDIuNQ0KdHJ1ZV9zY2FsZSA8LSAzLjANCg0KIyBDcmVhdGUgZGVuc2l0eSBwbG90IGNvbXBhcmluZyB0cnVlIGRpc3RyaWJ1dGlvbiBhbmQgZXN0aW1hdGVkDQp4X3JhbmdlIDwtIHNlcSgwLCBtYXgoeCksIGxlbmd0aC5vdXQgPSAyMDApDQp0cnVlX2RlbnMgPC0gZHdlaWJ1bGwoeF9yYW5nZSwgc2hhcGUgPSB0cnVlX3NoYXBlLCBzY2FsZSA9IHRydWVfc2NhbGUpDQptb21fZGVucyA8LSBkd2VpYnVsbCh4X3JhbmdlLCBzaGFwZSA9IDIuNTIsIHNjYWxlID0gMy4wMTEyKQ0KDQojIyByYW5kb20gc2FtcGxlDQpyYW5kLnNhbXBsZSA8LSByd2VpYnVsbCgyMDAsIHNoYXBlID0gdHJ1ZV9zaGFwZSwgc2NhbGUgPSB0cnVlX3NjYWxlKQ0KZCA8LSBkZW5zaXR5KHJhbmQuc2FtcGxlKQ0KcGRmX2ludGVycG9sYXRvciA8LSBhcHByb3hmdW4oZCR4LCBkJHkpDQojIw0KcGxvdF9kYXRhIDwtIGRhdGEuZnJhbWUoDQogIHggPSByZXAoeF9yYW5nZSwgMyksDQogIGRlbnNpdHkgPSBjKHRydWVfZGVucywgbW9tX2RlbnMsIHBkZl9pbnRlcnBvbGF0b3IoeF9yYW5nZSkpLA0KICBEaXN0cmlidXRpb24gPSByZXAoYygiVHJ1ZSBEZW5zaXR5IiwgIk1ldGhvZCBvZiBNb21lbnRzIiwgIlNhbXBsZSBEYXRhIChLREUpIiksIA0KICAgICAgICAgICAgICAgICAgICBlYWNoID0gbGVuZ3RoKHhfcmFuZ2UpKQ0KKQ0KDQp3ZWlidWxsLnBsdCA8LSBnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IHgsIHkgPSBkZW5zaXR5LCBjb2xvciA9IERpc3RyaWJ1dGlvbiwgbGluZXR5cGUgPSBEaXN0cmlidXRpb24pKSArDQogIGdlb21fbGluZShzaXplID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIldlaWJ1bGwgRGlzdHJpYnV0aW9uOiBUcnVlIHZzIE1ldGhvZCBvZiBNb21lbnRzIEVzdGltYXRpb24iLA0KICAgICAgIHggPSAiV2VpYnVsbCBTY29yZSIsIHkgPSAiVHJ1ZSBhbmQgRXN0aW1hdGVkIERlbnNpdHkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJUcnVlIERlbnNpdHkiID0gInJlZCIsICJNZXRob2Qgb2YgTW9tZW50cyIgPSAiYmx1ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTYW1wbGUgRGF0YSAoS0RFKSIgPSAiYmxhY2siKSkgKw0KICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygiVHJ1ZSBEZW5zaXR5IiA9ICJzb2xpZCIsICJNZXRob2Qgb2YgTW9tZW50cyIgPSAiZGFzaGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2FtcGxlIERhdGEgKEtERSkiID0gImRvdHRlZCIpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCmdncGxvdGx5KHdlaWJ1bGwucGx0KQ0KYGBgDQoNCg0KU2luY2UgdGhlIGRhdGEgd2FzIHNpbXVsYXRlZCBmcm9tIHRoZSBXZWlidWxsIHBvcHVsYXRpb24gd2l0aCBzaGFwZSAyLjUgYW5kIHNjYWxlIDMuIFRoZSBNTUUgb2YgdGhlIHNoYXBlIGFuZCBzY2FsZSBhcmUgdmVyeSBjbG9zZSB0byB0aGUgdHJ1ZSB2YWx1ZXMuIFRoZXJlZm9yZSwgdGhlIGVzdGltYXRlZCBwYXJhbWV0cmljIGRlbnNpdHkgY3VydmUgaXMgYWxtb3N0IGlkZW50aWNhbCB0byB0aGUgdHJ1ZSBkZW5zaXR5IGN1cnZlLiBUaGUgbm9ucGFyYW1ldHJpYyBrZXJuZWwgZGVuc2l0eSBjdXJ2ZSBpcyBzbGlnaHRseSBkaWZmZXJlbnQgZnJvbSB0aGUgdHJ1ZSBkZW5zaXR5IGN1cnZlLiBUaGlzIG1lYW5zIHRoYXQgPGZvbnQgY29sb3IgPSAiZGFya3JlZCI+KippZiB0aGUgZGlzdHJpYnV0aW9uIGlzIGNvcnJlY3RseSBzcGVjaWZpZWQsIHRoZSBwYXJhbWV0cmljIGRlbnNpdHkgZXN0aW1hdGlvbiBtb3JlIGVmZmljaWVudCB0aGFuIHRoZSBub25wYXJhbWV0cmljIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24uKio8L2ZvbnQ+ICANCg0KQXMgYSBnb29kIHByYWN0aWNlLCB5b3UgY2FuIHNpbXVsYXRlIGEgZGF0YXNldCBmcm9tIGEgV2VpYnVsbCBkaXN0cmlidXRpb24gYW5kIGF0dGVtcHQgdG8gZml0IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB0byBpdC4gUGxvdCB0aGUgdGhyZWUgcmVzdWx0aW5nIGRlbnNpdHkgY3VydmVz4oCUdGhlIHRydWUgV2VpYnVsbCwgdGhlIGVzdGltYXRlZCBub3JtYWwsIGFuZCBhIG5vbnBhcmFtZXRyaWMga2VybmVsIGRlbnNpdHnigJR0byBjb21wYXJlIHRoZSBwZXJmb3JtYW5jZSBvZiBwYXJhbWV0cmljIGFuZCBub25wYXJhbWV0cmljIGVzdGltYXRpb24gbWV0aG9kcy4NCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K